package tesis.sin.client.api;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.Vector;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;

import tesis.sin.model.AtributoPosteable;
import tesis.sin.model.Mensaje;
import tesis.sin.model.Noticia;
import tesis.sin.model.Posteable;
import tesis.sin.rest.parser.JsonParser;
import tesis.sin.rest.servicios.DirectorioServicios;

public class API {

	private static Client cliente = ClientBuilder.newClient();
	private static final URI BASE_URI = URI.create("http://tesis.serveftp.com:8080/SIN/rest");

	public static Response postMensaje(Mensaje mensaje) throws IOException
	{
		String json = JsonParser.objetoAJson(mensaje);
		Form formData = new Form(); 
		formData.param("json", json);
		Response response = API.cliente.target(UriBuilder.fromUri(API.BASE_URI).path(DirectorioServicios.SERVICIO_POST_MENSAJE).build()).request(MediaType.TEXT_PLAIN_TYPE).post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED_TYPE), Response.class);
		return response;
	}

	public static Response postNoticia(Noticia noticia) throws IOException
	{
		String json = JsonParser.objetoAJson(noticia);
		Form formData = new Form(); 
		formData.param("json", json);
		Response response = API.cliente.target(UriBuilder.fromUri(API.BASE_URI).path(DirectorioServicios.SERVICIO_POST_NOTICIA).build()).request(MediaType.TEXT_PLAIN_TYPE).post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED_TYPE), Response.class);
		return response;
	}

	public static Response post(Object posteable) throws Exception
	{
		String json = JsonParser.objetoAJson(posteable, API.getPropiedadesPosteables(posteable));
		Form formData = new Form(); 
		formData.param("nombreClase", posteable.getClass().getName());
		formData.param("json", json);
		Response response = API.cliente.target(UriBuilder.fromUri(API.BASE_URI).path(DirectorioServicios.SERVICIO_POST_OBJETO).build()).request(MediaType.TEXT_PLAIN_TYPE).post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED_TYPE), Response.class);
		return response;
	}

	public static Response get(Class posteable, Object value) throws Exception
	{
		String params = API.getURLGet(posteable, value);
		URL url = UriBuilder.fromUri(API.BASE_URI).path(DirectorioServicios.SERVICIO_GET_OBJETO + params).build().toURL();
		Client client = ClientBuilder.newClient();
		WebTarget webTarget = client.target(url.toString());
		Invocation.Builder invocationBuilder = webTarget.request(MediaType.TEXT_PLAIN_TYPE);
		Response response = invocationBuilder.get();
		return response;
	}

	private static String getURLGet(Class posteable, Object value) throws Exception  {
		if(posteable.isAnnotationPresent(Posteable.class))
		{
			BeanInfo info = Introspector.getBeanInfo(posteable);  
			PropertyDescriptor[] props = info.getPropertyDescriptors();  
			for(PropertyDescriptor pd : props) 
			{  
				if(pd.getName().equals("class"))
					continue;
				Field f = posteable.getDeclaredField(pd.getName());
				if(f.isAnnotationPresent(AtributoPosteable.class) && f.getAnnotation(AtributoPosteable.class).identificador())
					return "/" + posteable.getName() + "/" + f.getName() + "/" + value;
			}
			throw new Exception(posteable.getName() + " no es una clase posteable.");
		}
		throw new Exception(posteable.getName() + " no es una clase posteable.");
	}

	private static String[] getPropiedadesPosteables(Object posteable) throws Exception {
		List<String> propiedades = new Vector<String>();
		boolean identificadorPresente = false;
		if(posteable.getClass().isAnnotationPresent(Posteable.class))
		{
			for(Field f : posteable.getClass().getDeclaredFields())
			{
				if(f.isAnnotationPresent(AtributoPosteable.class))
				{
					propiedades.add(f.getName());
					if(!identificadorPresente)
						identificadorPresente = f.getAnnotation(AtributoPosteable.class).identificador();
				}
			}

			if(!propiedades.isEmpty())
			{
				if(!identificadorPresente)
					throw new Exception(posteable.getClass().getName() + " no especifica atributo identificador.");

				return propiedades.toArray(new String[propiedades.size()]);
			}

			throw new Exception(posteable.getClass().getName() + " no especifica atributos posteables.");
		}
		throw new Exception(posteable.getClass().getName() + " no es una clase posteable.");
	}
}